﻿using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace System
{
    /// <summary>Методы-расширения класса <see cref="T:System.String">строк</see></summary>
    public static class StringExtentions
    {
        public static string GetBracketText(this string Str, ref int Offset, string Open = "(", string Close = ")")
        {
            var Start = Str.IndexOf(Open, Offset, StringComparison.Ordinal);
            if(Start == -1) return null;
            var Stop = Str.IndexOf(Close, Start + 1, StringComparison.Ordinal);
            if(Stop == -1)
                throw new FormatException();
            var start = Start;
            do
            {
                start = Str.IndexOf(Open, start + 1, StringComparison.Ordinal);
                if(start != -1 && start < Stop)
                    Stop = Str.IndexOf(Close, Stop + 1, StringComparison.Ordinal);
            } while(start != -1 && start < Stop);
            if(Stop == -1 || Stop < Start)
                throw new FormatException();
            Offset = Stop + Close.Length;
            Start += Open.Length;
            return Str.Substring(Start, Stop - Start);
        }

        public static string GetBracketText(this string Str, ref int Offset, string Open, string Close,
            out string TextBefore, out string TextAfter)
        {
            TextAfter = null;
            var Start = Str.IndexOf(Open, Offset, StringComparison.Ordinal);
            if(Start == -1)
            {
                TextBefore = Str.Substring(Offset, Str.Length - Offset);
                return null;
            }
            var Stop = Str.IndexOf(Close, Start + 1, StringComparison.Ordinal);
            if(Stop == -1)
                throw new FormatException();
            var start = Start;
            do
            {
                start = Str.IndexOf(Open, start + 1, StringComparison.Ordinal);
                if(start != -1 && start < Stop)
                    Stop = Str.IndexOf(Close, Stop + 1, StringComparison.Ordinal);
            } while(start != -1 && start < Stop);
            if(Stop == -1 || Stop < Start)
                throw new FormatException();
            TextBefore = Str.Substring(Offset, Start - Offset);
            Offset = Stop + Close.Length;
            TextAfter = Str.Length - Offset > 0 ? Str.Substring(Offset, Str.Length - Offset) : "";
            Start += Open.Length;
            return Str.Substring(Start, Stop - Start);
        }

        /// <summary>Проверка строки на пустоту, либо нулевую ссылку</summary>
        /// <param name="Str">Проверяемая строка</param>
        /// <returns>Истина, если трока пуста, либо если передана нулевая ссылка</returns>
        [DebuggerStepThrough, Pure]
        public static bool IsNullOrEmpty(this string Str) { return string.IsNullOrEmpty(Str); }

        /// <summary>Удаление символов в начале строки</summary>
        /// <param name="str">Обрабатываемая строка</param>
        /// <param name="symbols">Перечень удаляемых символов</param>
        /// <returns>Новая строка с удалёнными символами в начале</returns>
        public static string ClerSymbolsAtBegin(this string str, params char[] symbols)
        {
            var i = 0;
            var len = str.Length;
            while(i < len && symbols.IsContains(str[i])) i++;

            return i == 0 || len == 0 ? str : str.Substring(i, len - i);
        }

        /// <summary>Удаление символов в конце строки</summary>
        /// <param name="str">Обрабатываемая строка</param>
        /// <param name="symbols">Перечень удаляемых символов</param>
        /// <returns>Новая строка с удалёнными символами в конце</returns>
        public static string ClerSymbolsAtEnd(this string str, params char[] symbols)
        {
            var len = str.Length;
            var i = 0;
            while(i < len && symbols.IsContains(str[len - i - 1])) i++;

            return len == 0 || i == 0 ? str : str.Substring(0, len - i);
        }

        /// <summary>Удаление символов в начале и конце строки</summary>
        /// <param name="str">Обрабатываемая строка</param>
        /// <param name="symbols">Перечень удаляемых символов</param>
        /// <returns>Новая строка с удалёнными символами в начале и конце</returns>
        public static string ClearSymbolsAtBeginAndEnd(this string str, params char[] symbols)
        {
            return str.ClerSymbolsAtBegin(symbols).ClerSymbolsAtEnd(symbols);
        }

        /// <summary>Удаление служебных символов в начале и конце строки</summary>
        /// <param name="str">Обрабатываемая строка</param>
        /// <returns>Новая строка с удалёнными служебными символами в началеи конце</returns>
        public static string ClearSystemSymbolsAtBeginAndEnd(this string str)
        {
            return str.ClearSymbolsAtBeginAndEnd(' ', '\n', '\r');
        }


    }
}
